package com.qingyun.tiktok.basis.service;


import com.qingyun.tiktok.basis.service.interfaces.Auth2Service;
import com.qingyun.tiktok.common.bean.ClientToken;
import com.qingyun.tiktok.common.bean.RefreshToken;
import com.qingyun.tiktok.common.bean.Ticket;
import com.qingyun.tiktok.common.config.DyOpenApiConfig;
import com.qingyun.tiktok.common.enums.ApiPlatform;
import com.qingyun.tiktok.common.enums.Auth2;
import com.qingyun.tiktok.common.exception.ApiCallException;
import com.qingyun.tiktok.common.exception.LandExpirationException;
import com.qingyun.tiktok.common.http.HttpExecutor;
import com.qingyun.tiktok.common.response.auth.AccessTokenRes;
import com.qingyun.tiktok.common.response.auth.ClientTokenRes;
import com.qingyun.tiktok.common.response.auth.RenewRefreshTokenRes;
import com.qingyun.tiktok.common.response.auth.TicketRes;
import com.qingyun.tiktok.common.service.BaseDyService;
import com.qingyun.tiktok.common.storage.DyStorageManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @author mdmbct  mdmbct@outlook.com
 * @date 2021/3/9 11:31
 * @modified mdmbct
 * @since 1.0
 */
@Slf4j
public class Auth2ServiceImpl extends BaseDyService implements Auth2Service {

    private final DyOpenApiConfig apiConfig;

    public Auth2ServiceImpl(DyStorageManager storageManager, HttpExecutor httpExecutor) {
        super(storageManager, httpExecutor);
        apiConfig = storageManager.getOpenApiConfig();
    }

    @Override
    public AccessTokenRes.AccessTokenResData authAccessToken(String code, ApiPlatform apiPlatform) throws ApiCallException {
        return authService.authAccessToken(code, apiPlatform);
    }

    @Override
    public AccessTokenRes.AccessTokenResData authExchangeAccessToken(String openId, ApiPlatform apiPlatform) throws ApiCallException {

        RefreshToken refreshToken = storageManager.getRefreshToken(openId);
        if (refreshToken == null) {
            log.error(LandExpirationException.DEFAULT_MSG);
            throw new LandExpirationException();
        }
        return authService.requestAccessTokenByRefreshToken(refreshToken, apiPlatform);
    }

    @Override
    public RenewRefreshTokenRes.RenewRefreshTokenResData renewRefreshToken(String openId) throws ApiCallException {

        RefreshToken oldRefreshToken = storageManager.getRefreshToken(openId);
        if (oldRefreshToken == null) {
            throw new LandExpirationException();
        }

        return authService.requestRefreshTokenByOld(oldRefreshToken, openId);
    }

    @Override
    public ClientTokenRes.ClientTokenResData authClientToken(ApiPlatform platform) throws ApiCallException{

        String url = formatRequestUrl(Auth2.OAUTH_CLIENT_TOKEN, platform, apiConfig.getApp().getKey(), apiConfig.getApp().getSecret());
        String result = httpExecutor.executeGet(null, url);
        ClientTokenRes.ClientTokenResData data = handleApiResponse(result, ClientTokenRes.class, ClientTokenRes.ClientTokenResData.class);
        storageManager.saveClientToken(new ClientToken(data.getExpiresIn() * 1000L, data.getAccessToken()));
        return data;
    }




	@Override
	public Ticket getTicket(ApiPlatform platform) throws ApiCallException {
		List defaultHeaders = Arrays.asList(

			new BasicHeader("X-Default-Header", "default header httpclient"));

		CloseableHttpClient httpclient = HttpClients

			.custom()

			.setDefaultHeaders(defaultHeaders)

			.build();

		try {
// setting custom http headers on the http request

			HttpUriRequest request = RequestBuilder.get()

				.setUri("https://open.douyin.com/open/getticket")

				.setHeader(HttpHeaders.CONTENT_TYPE, "application/json")

				.setHeader("access-token", storageManager.getClientToken().getValue())

				.build();

			System.out.println("Executing request " + request.getRequestLine());

// Create a custom response handler

			ResponseHandler responseHandler = response -> {
				int status = response.getStatusLine().getStatusCode();

				if (status >= 200) {

					HttpEntity entity = response.getEntity();

					return entity != null ? EntityUtils.toString(entity) : null;

				} else {
					throw new ClientProtocolException("Unexpected response status: " + status);

				}

			};

			String responseBody = null;
			try {
				responseBody = (String) httpclient.execute(request, responseHandler);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}

			System.out.println("----------------------------------------");
			System.out.println(responseBody);
			TicketRes.TicketResData data = handleApiResponse(responseBody, TicketRes.class, TicketRes.TicketResData.class);
			Ticket ticket = new Ticket(data.getExpiresIn() * 1000L, data.getTicket());
			storageManager.saveTicket(ticket);
			return ticket;
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}


}
